/**********************************************************************************************************
** 驱动文件：	dianli-EM303E.c
** 驱动类型：	dianli
** 设备名称：	电力监测
** 设备型号：	EM303E
** 设备品牌：	融智云
** 设备协议：	Modbus-RTU
** 驱动描述：	EM303E三相综合电力电量仪，具备实时电压、电流、频率、电能、有功、无功等电量采集功能。
** 生成日期：	2019-11-30 16:16:37
**********************************************************************************************************/
#include "Includes.h"


/**********************************************************************************************************
* 定义设备数据点变量结构
**********************************************************************************************************/
typedef struct{
	Var Ua;										//A相电压
	Var Ub;										//B相电压
	Var Uc;										//C相电压
	Var Ia;										//A相电流
	Var Ib;										//B相电流
	Var Ic;										//C相电流
	Var Psum;									//总有功功率
	Var Pa;										//A相有功功率
	Var Pb;										//B相有功功率
	Var Pc;										//C相有功功率
	Var Qsum;									//总无功功率
	Var Qa;										//A相无功功率
	Var Qb;										//B相无功功率
	Var Qc;										//C相无功功率
	Var Ssum;									//总视在功率
	Var Sa;										//A相视在功率
	Var Sb;										//B相视在功率
	Var Sc;										//C相视在功率
	Var COSsum;									//总功率因数
	Var COSa;									//A相功率因数
	Var COSb;									//B相功率因数
	Var COSc;									//C相功率因数
	Var FRa;									//A相电压频率
	Var FRb;									//B相电压频率
	Var FRc;									//C相电压频率
	Var EpForward;								//正向有功电能
	Var EpReverse;								//反向有功电能
	Var EqForward;								//正向无功电能
	Var EqReverse;								//反向无功电能
	Var PT;										//电压变比设定
	Var CT;										//电流变比设定
}Data_Struct;									//定义变量结构


/**********************************************************************************************************
* 设备数据点变量属性声明
**********************************************************************************************************/
const static Var_Property_Def var_attr[] = {
	{
		FLOAT,
		0,
		READONLY,
		"Ua",
		"A相电压",
		"V",
		"A相电压",
		0,
		0,
		"A相电压过高",
		"A相电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Ub",
		"B相电压",
		"V",
		"B相电压",
		0,
		0,
		"B相电压过高",
		"B相电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Uc",
		"C相电压",
		"V",
		"C相电压",
		0,
		0,
		"C相电压过高",
		"C相电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Ia",
		"A相电流",
		"A",
		"A相电流",
		0,
		0,
		"A相电流过高",
		"A相电流过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Ib",
		"B相电流",
		"A",
		"B相电流",
		0,
		0,
		"B相电流过高",
		"B相电流过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Ic",
		"C相电流",
		"A",
		"C相电流",
		0,
		0,
		"C相电流过高",
		"C相电流过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Psum",
		"总有功功率",
		"W",
		"总有功功率",
		0,
		0,
		"总有功功率过高",
		"总有功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Pa",
		"A相有功功率",
		"W",
		"A相有功功率",
		0,
		0,
		"A相有功功率过高",
		"A相有功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Pb",
		"B相有功功率",
		"W",
		"B相有功功率",
		0,
		0,
		"B相有功功率过高",
		"B相有功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Pc",
		"C相有功功率",
		"W",
		"C相有功功率",
		0,
		0,
		"C相有功功率过高",
		"C相有功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Qsum",
		"总无功功率",
		"Var",
		"总无功功率",
		0,
		0,
		"总无功功率过高",
		"总无功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Qa",
		"A相无功功率",
		"Var",
		"A相无功功率",
		0,
		0,
		"A相无功功率过高",
		"A相无功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Qb",
		"B相无功功率",
		"Var",
		"B相无功功率",
		0,
		0,
		"B相无功功率过高",
		"B相无功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Qc",
		"C相无功功率",
		"Var",
		"C相无功功率",
		0,
		0,
		"C相无功功率过高",
		"C相无功功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Ssum",
		"总视在功率",
		"VA",
		"总视在功率",
		0,
		0,
		"总视在功率过高",
		"总视在功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Sa",
		"A相视在功率",
		"VA",
		"A相视在功率",
		0,
		0,
		"A相视在功率过高",
		"A相视在功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Sb",
		"B相视在功率",
		"VA",
		"B相视在功率",
		0,
		0,
		"B相视在功率过高",
		"B相视在功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Sc",
		"C相视在功率",
		"VA",
		"C相视在功率",
		0,
		0,
		"C相视在功率过高",
		"C相视在功率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"COSsum",
		"总功率因数",
		"",
		"总功率因数",
		0,
		0,
		"总功率因数过高",
		"总功率因数过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"COSa",
		"A相功率因数",
		"",
		"A相功率因数",
		0,
		0,
		"A相功率因数过高",
		"A相功率因数过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"COSb",
		"B相功率因数",
		"",
		"B相功率因数",
		0,
		0,
		"B相功率因数过高",
		"B相功率因数过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"COSc",
		"C相功率因数",
		"",
		"C相功率因数",
		0,
		0,
		"C相功率因数过高",
		"C相功率因数过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"FRa",
		"A相电压频率",
		"Hz",
		"A相电压频率",
		0,
		0,
		"A相电压频率过高",
		"A相电压频率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"FRb",
		"B相电压频率",
		"Hz",
		"B相电压频率",
		0,
		0,
		"B相电压频率过高",
		"B相电压频率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"FRc",
		"C相电压频率",
		"Hz",
		"C相电压频率",
		0,
		0,
		"C相电压频率过高",
		"C相电压频率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"EpForward",
		"正向有功电能",
		"KW•h",
		"正向有功电能",
		0,
		0,
		"正向有功电能过高",
		"正向有功电能过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"EpReverse",
		"反向有功电能",
		"KW•h",
		"反向有功电能",
		0,
		0,
		"反向有功电能过高",
		"反向有功电能过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"EqForward",
		"正向无功电能",
		"KVar•h",
		"正向无功电能",
		0,
		0,
		"正向无功电能过高",
		"正向无功电能过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"EqReverse",
		"反向无功电能",
		"KVar•h",
		"反向无功电能",
		0,
		0,
		"反向无功电能过高",
		"反向无功电能过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READWRITE,
		"PT",
		"电压变比设定",
		"",
		"电压变比设定",
		0,
		0,
		"",
		"",
		1,
		0
	},
	{
		FLOAT,
		0,
		READWRITE,
		"CT",
		"电流变比设定",
		"",
		"电流变比设定",
		0,
		0,
		"",
		"",
		1,
		0
	}
};


/**********************************************************************************************************
* 函数名称： static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
* 函数说明： 生成获取传感器数据指令
* 输入参数： 指令索引，传感器地址，变量结构体指针,以及指令缓存区指针,指令长度
* 返回参数： 无
**********************************************************************************************************/
static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
{
	Data_Struct 	*d = (Data_Struct*)data;
	switch(index)
	{
		case 0:
			if(d->PT.status==NewSet||d->CT.status==NewSet){
				cmd[0] = addr;
				cmd[1] = 0x03;
				cmd[2] = 0x00;								
				cmd[3] = 0x59;
				cmd[4] = 0x00;	
				cmd[5] = 0x02;
				*len = CRC16_Padding(cmd, 6);
			}
			else{
				*len  = -1;
			}
			break;
		case 1:
			cmd[0] = addr;
			cmd[1] = 0x03;
			cmd[2] = 0x00;								
			cmd[3] = 0x00;
			cmd[4] = 0x00;	
			cmd[5] = 0x26;
			*len = CRC16_Padding(cmd, 6);
			break;
		default:
			break;
	}
}


/**********************************************************************************************************
* 函数名称： static int parse_fun(short index, int addr, void *data, char *buf, short len)
* 函数说明： 解析传感器响应的数据，并写入数据库
* 输入参数： 解析索引,传感器地址，变量结构体指针，以及响应数据缓存取指针，响应数据长度
* 返回参数： 返回解析结果，返回0成功，返回1失败
**********************************************************************************************************/
static int parse_fun(short index, int addr, void *data, char *buf, short len)
{
	union{
		short 			dat16;
      	unsigned char  	dat8[2];
    }DAT16_8;							//数据类型转换	
    union 		   					 
    {
		unsigned int	dat32;
		unsigned char   dat8[4];
    }DAT32_8;							//数据类型转换		
	Data_Struct 	*d = (Data_Struct*)data;
	
	if(buf!=NULL && buf[0]==addr && len>0 )
	{	
		if(CRC16_Check(buf,len))
		{
			switch(index)
			{
				case 0:
					d->PT.status	= Normal;
					d->CT.status	= Normal;
					DAT16_8.dat8[1] = buf[3];
					DAT16_8.dat8[0] = buf[4];
					d->PT.value.fnum= DAT16_8.dat16*1.0f;
					DAT16_8.dat8[1] = buf[5];
					DAT16_8.dat8[0] = buf[6];
					d->CT.value.fnum= DAT16_8.dat16*1.0f;				
					break;
				case 1:	
					DAT16_8.dat8[1] = buf[3];
					DAT16_8.dat8[0] = buf[4];
					d->Ua.value.fnum = DAT16_8.dat16*d->PT.value.fnum*0.1f;
					DAT16_8.dat8[1] = buf[5];
					DAT16_8.dat8[0] = buf[6];
					d->Ub.value.fnum = DAT16_8.dat16*d->PT.value.fnum*0.1f;
					DAT16_8.dat8[1] = buf[7];
					DAT16_8.dat8[0] = buf[8];
					d->Uc.value.fnum = DAT16_8.dat16*d->PT.value.fnum*0.1f;

					DAT16_8.dat8[1] = buf[9];
					DAT16_8.dat8[0] = buf[10];
					d->Ia.value.fnum = DAT16_8.dat16*d->CT.value.fnum*0.001f;
					DAT16_8.dat8[1] = buf[11];
					DAT16_8.dat8[0] = buf[12];
					d->Ib.value.fnum = DAT16_8.dat16*d->CT.value.fnum*0.001f;
					DAT16_8.dat8[1] = buf[13];
					DAT16_8.dat8[0] = buf[14];
					d->Ic.value.fnum = DAT16_8.dat16*d->CT.value.fnum*0.001f;
				
					DAT16_8.dat8[1] = buf[17];
					DAT16_8.dat8[0] = buf[18];
					d->Psum.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;					
					DAT16_8.dat8[1] = buf[19];
					DAT16_8.dat8[0] = buf[20];
					d->Pa.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					DAT16_8.dat8[1] = buf[21];
					DAT16_8.dat8[0] = buf[22];
					d->Pb.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					DAT16_8.dat8[1] = buf[23];
					DAT16_8.dat8[0] = buf[24];
					d->Pc.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;			
				
					DAT16_8.dat8[1] = buf[25];
					DAT16_8.dat8[0] = buf[26];
					d->Qsum.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;			
					DAT16_8.dat8[1] = buf[27];
					DAT16_8.dat8[0] = buf[28];
					d->Qa.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					DAT16_8.dat8[1] = buf[29];
					DAT16_8.dat8[0] = buf[30];
					d->Qb.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					DAT16_8.dat8[1] = buf[31];
					DAT16_8.dat8[0] = buf[32];
					d->Qc.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					
					DAT16_8.dat8[1] = buf[33];
					DAT16_8.dat8[0] = buf[34];
					d->Ssum.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;			
					DAT16_8.dat8[1] = buf[35];
					DAT16_8.dat8[0] = buf[36];
					d->Sa.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					DAT16_8.dat8[1] = buf[37];
					DAT16_8.dat8[0] = buf[38];
					d->Sb.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					DAT16_8.dat8[1] = buf[39];
					DAT16_8.dat8[0] = buf[40];
					d->Sc.value.fnum = DAT16_8.dat16*d->PT.value.fnum*d->CT.value.fnum*1.0f;
					
					DAT16_8.dat8[1] = buf[41];
					DAT16_8.dat8[0] = buf[42];
					d->COSsum.value.fnum = DAT16_8.dat16*0.001f;				
					DAT16_8.dat8[1] = buf[43];
					DAT16_8.dat8[0] = buf[44];
					d->COSa.value.fnum = DAT16_8.dat16*0.001f;
					DAT16_8.dat8[1] = buf[45];
					DAT16_8.dat8[0] = buf[46];
					d->COSb.value.fnum = DAT16_8.dat16*0.001f;
					DAT16_8.dat8[1] = buf[47];
					DAT16_8.dat8[0] = buf[48];
					d->COSc.value.fnum = DAT16_8.dat16*0.001f;		
					
					DAT16_8.dat8[1] = buf[55];
					DAT16_8.dat8[0] = buf[56];
					d->FRa.value.fnum = DAT16_8.dat16*0.01f;
					DAT16_8.dat8[1] = buf[57];
					DAT16_8.dat8[0] = buf[58];
					d->FRb.value.fnum = DAT16_8.dat16*0.01f;
					DAT16_8.dat8[1] = buf[59];
					DAT16_8.dat8[0] = buf[60];
					d->FRc.value.fnum = DAT16_8.dat16*0.01f;

					DAT32_8.dat8[3] = buf[61];
					DAT32_8.dat8[2] = buf[62];
					DAT32_8.dat8[1] = buf[63];
					DAT32_8.dat8[0] = buf[64];
					d->EpForward.value.fnum = DAT32_8.dat32*d->PT.value.fnum*d->CT.value.fnum*0.01f;
					
					DAT32_8.dat8[3] = buf[65];
					DAT32_8.dat8[2] = buf[66];
					DAT32_8.dat8[1] = buf[67];
					DAT32_8.dat8[0] = buf[68];
					d->EpReverse.value.fnum = DAT32_8.dat32*d->PT.value.fnum*d->CT.value.fnum*0.01f;
					
					DAT32_8.dat8[3] = buf[69];
					DAT32_8.dat8[2] = buf[70];
					DAT32_8.dat8[1] = buf[71];
					DAT32_8.dat8[0] = buf[72];
					d->EqForward.value.fnum = DAT32_8.dat32*d->PT.value.fnum*d->CT.value.fnum*0.01f;
					
					DAT32_8.dat8[3] = buf[73];
					DAT32_8.dat8[2] = buf[74];
					DAT32_8.dat8[1] = buf[75];
					DAT32_8.dat8[0] = buf[76];
					d->EqReverse.value.fnum = DAT32_8.dat32*d->PT.value.fnum*d->CT.value.fnum*0.01f;
					break;			
				default:
					break;
			}
			return 0;
		}
	}
	return 1;
}


/**********************************************************************************************************
* 函数名称： void dianli_EM303E_Registration(void)
* 函数说明： 电力监测驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void dianli_EM303E_Registration(void)
{
	DeviceDriverRegistration(
		"dianli",												//设备类型
		"电力监测",												//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"EM303E",												//设备型号
		"EM303E三相综合电力电量仪，具备实时电压、电流、频率、电能、有功、无功等电量采集功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		250														//设备响应超时时间
	);

#if 0 || VirtualFrameEN
	#define CMD1 "\x14\x03\x00\x59\x00\x02\x16\xDD"
	#define RSP1 "\x14\x03\x04\x00\x01\x00\x01\x2E\xF2"	
	#define CMD2 "\x14\x03\x00\x00\x00\x26\xC6\xD5"
	#define RSP2 "\x14\x03\x4C\x09\x2E\x09\x2B\x09\x2D\x2C\x5A\x18\xD2\x3F\xE1\x00\x00\x1D\xCC\x09\xE3\x07\xB2\x0B\x99\x00\x99\x00\x38\x00\x49\x00\x57\x1E\xCC\x09\xF3\x07\xF2\x0B\xF9\x03\x61\x03\x5B\x03\x51\x03\x74\x0E\xC9\x0E\xC9\x0E\xC9\x13\x87\x13\x87\x13\x87\x00\x00\x16\x2F\x00\x00\x00\xEC\x00\x00\x0A\x3A\x00\x00\x00\xB9\x9F\x9C"		
		
	VirtualFrameRegistration(CMD1, sizeof(CMD1)-1, RSP1, sizeof(RSP1)-1);
	VirtualFrameRegistration(CMD2, sizeof(CMD2)-1, RSP2, sizeof(RSP2)-1);
#endif
}

